package com.lonely.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lonely.system.domain.entity.SysUser;
import com.lonely.common.utils.SecurityUtils;
import com.lonely.system.domain.entity.SysDataPermissions;
import com.lonely.system.domain.entity.SysFactory;
import com.lonely.system.domain.entity.SysProductionLine;
import com.lonely.system.domain.dto.user.BindUserDataPermissionsDto;
import com.lonely.system.domain.vo.system.user.SysUserDetailVo;
import com.lonely.system.enums.SysFactoryEnum;
import com.lonely.system.enums.SysProductionLineEnum;
import com.lonely.system.mapper.SysDataPermissionsMapper;
import com.lonely.system.service.ISysDataPermissionsService;
import com.lonely.system.service.ISysFactoryService;
import com.lonely.system.service.ISysProductionLineService;
import com.lonely.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: 黄志标
 * @date: 2025/6/3 14:47
 * @description: 数据权限接口实现类
 */
@Service
public class SysDataPermissionsServiceImpl extends ServiceImpl<SysDataPermissionsMapper, SysDataPermissions> implements ISysDataPermissionsService {

    @Autowired
    private ISysFactoryService sysFactoryService;

    @Autowired
    private ISysProductionLineService sysProductionLineService;

    @Autowired
    private ISysUserService sysUserService;


    /**
     * 获取用户数据权限
     *
     * @param userId
     * @return
     */
    @Override
    public SysUserDetailVo.OrganizationInfo getOrganizationsByUserId(Long userId) {
        // 1. 获取用户对应的数据权限信息
        List<SysDataPermissions> dataPermissions = this.list(new LambdaQueryWrapper<SysDataPermissions>().eq(SysDataPermissions::getUserId, userId));
        List<Long> existsFactoryIds = dataPermissions.stream().map(SysDataPermissions::getFactoryId).distinct().collect(Collectors.toList());
        List<Long> existsPlIds = dataPermissions.stream().map(SysDataPermissions::getProductionLineId).distinct().collect(Collectors.toList());

        // 2. 初始化数据权限结构
        // 获取工厂列表
        List<SysFactory> factorys = this.sysFactoryService.list(new LambdaQueryWrapper<SysFactory>().eq(SysFactory::getStatus, SysFactoryEnum.FactoryStatus.ENABLE.status));

        // 全部生产组织
        SysUserDetailVo.OrganizationInfo organizationInfo = new SysUserDetailVo.OrganizationInfo();
        organizationInfo.setChecked(false);
        organizationInfo.setLabel("全部生产组织");
        organizationInfo.setValue("allFactorys");

        List<SysUserDetailVo.BranchFactory> userBranchFactoryList = new ArrayList<>();
        organizationInfo.setUserBranchFactoryList(userBranchFactoryList);

        // 没有工厂
        if (CollUtil.isEmpty(factorys)) {
            return organizationInfo;
        }
        for (SysFactory factory : factorys) {
            userBranchFactoryList.add(extractBranchFactory(factory, existsFactoryIds, existsPlIds));
        }
        if (CollUtil.isNotEmpty(userBranchFactoryList)) {
            organizationInfo.setChecked(userBranchFactoryList.stream().allMatch(SysUserDetailVo.BranchFactory::isChecked));
        }
        return organizationInfo;
    }

    /**
     * 绑定用户数据权限关联
     *
     * @param bindUserDataPermissionsDto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void bindUserPermissions(BindUserDataPermissionsDto bindUserDataPermissionsDto) {

        // 验证用户的有效性
        SysUser user = this.sysUserService.getById(bindUserDataPermissionsDto.getUserId());
        Assert.notNull(user, "用户不存在");

        // 删除老数据
        super.remove(new LambdaQueryWrapper<SysDataPermissions>().eq(SysDataPermissions::getUserId, bindUserDataPermissionsDto.getUserId()));

        // 获取产线对应的数据
        if (CollUtil.isEmpty(bindUserDataPermissionsDto.getProductionLineIds())) {
            return;
        }

        List<SysDataPermissions> permissions = Optional.ofNullable(this.sysProductionLineService.list(new LambdaQueryWrapper<SysProductionLine>().in(SysProductionLine::getId, bindUserDataPermissionsDto.getProductionLineIds())))
                .orElse(new ArrayList<>()).stream().map(x -> {
                    SysDataPermissions dataPermissions = new SysDataPermissions();
                    dataPermissions.setUserId(bindUserDataPermissionsDto.getUserId());
                    dataPermissions.setFactoryId(x.getFactoryId());
                    dataPermissions.setProductionLineId(x.getId());
                    dataPermissions.setCreateBy(SecurityUtils.getUserId());
                    dataPermissions.setUpdateBy(SecurityUtils.getUserId());
                    return dataPermissions;
                }).collect(Collectors.toList());

        if (CollUtil.isNotEmpty(permissions)) {
            super.saveBatch(permissions);
        }
    }

    /**
     * 获取指定用户的工厂数据权限
     *
     * @param userId
     * @return
     */
    @Override
    public Set<String> getFactoryDataPermissions(Long userId) {
        return super.list(new LambdaQueryWrapper<SysDataPermissions>().eq(SysDataPermissions::getUserId, userId))
                .stream().map(SysDataPermissions::getFactoryId)
                .filter(Objects::nonNull)
                .distinct()
                .map(StrUtil::toString)
                .collect(Collectors.toSet());
    }

    /**
     * 提取使用的工厂信息
     *
     * @param factory
     * @param existsFactoryIds
     * @param existsPlIds
     * @return
     */
    private SysUserDetailVo.BranchFactory extractBranchFactory(SysFactory factory, List<Long> existsFactoryIds, List<Long> existsPlIds) {
        SysUserDetailVo.BranchFactory currentBranchFactory = new SysUserDetailVo.BranchFactory();
        currentBranchFactory.setChecked(existsFactoryIds.contains(factory.getId()));
        currentBranchFactory.setLabel(String.format("%s全部产线/分组", factory.getName()));
        currentBranchFactory.setValue(Convert.toStr(factory.getId()));

        // 获取产线列表
        List<SysProductionLine> productionLines = this.sysProductionLineService.list(new LambdaQueryWrapper<SysProductionLine>().eq(SysProductionLine::getFactoryId, factory.getId()));
        // 产线分组
        currentBranchFactory.setUserProcessList(extractUserProcessList(productionLines, existsPlIds));
        return currentBranchFactory;
    }


    /**
     * 提取使用的产线组配置
     *
     * @param productionLines
     * @param existsPlIds
     * @return
     */
    private List<SysUserDetailVo.ProcessInfo> extractUserProcessList(List<SysProductionLine> productionLines, List<Long> existsPlIds) {

        if (CollUtil.isEmpty(productionLines)) {
            return new ArrayList<>();
        }

        List<SysUserDetailVo.ProcessInfo> userProcessList = new ArrayList<>();
        LinkedHashMap<Integer, List<SysProductionLine>> plGroups = productionLines.stream().collect(Collectors.groupingBy(SysProductionLine::getType, LinkedHashMap::new, Collectors.toList()));
        for (Map.Entry<Integer, List<SysProductionLine>> currentPlGroup : plGroups.entrySet()) {
            // 判断当前组下是否有产线
            if (CollUtil.isEmpty(currentPlGroup.getValue())) {
                // 没有产线，则跳过
                continue;
            }
            // 有产线
            SysUserDetailVo.ProcessInfo processInfo = new SysUserDetailVo.ProcessInfo();
            processInfo.setLabel(generatorPlGroupName(currentPlGroup.getKey()));
            processInfo.setValue(null);
            processInfo.setUserLineList(convertToLineInfos(currentPlGroup.getValue(), existsPlIds));
            boolean allChecked = processInfo.getUserLineList().stream().allMatch(SysUserDetailVo.LineInfo::isChecked);
            processInfo.setChecked(allChecked);
            userProcessList.add(processInfo);
        }
        return userProcessList;
    }


    /**
     * 生成产线分组名称
     *
     * @param plGroupType
     * @return
     */
    private String generatorPlGroupName(Integer plGroupType) {
        String labelName = null;
        switch (SysProductionLineEnum.ProductionLineType.getInstance(plGroupType)) {
            case FUNCTION_GROUP:
                labelName = "职能";
                break;
            case TAILOR_GROUP:
                labelName = "裁剪";
                break;
            case SEWING_GROUP:
                labelName = "车缝";
                break;
            case POST_WHOLE_GROUP:
                labelName = "后整";
                break;
        }

        return String.format("全部%s产线/分组", labelName);
    }

    /**
     * 转换产线信息
     *
     * @param currentPls
     * @param existsPlIds
     * @return
     */
    private List<SysUserDetailVo.LineInfo> convertToLineInfos(List<SysProductionLine> currentPls, List<Long> existsPlIds) {
        List<SysUserDetailVo.LineInfo> lineInfos = new ArrayList<>();
        for (SysProductionLine currentPl : currentPls) {
            SysUserDetailVo.LineInfo lineInfo = new SysUserDetailVo.LineInfo();
            lineInfo.setChecked(existsPlIds.contains(currentPl.getId()));
            lineInfo.setLabel(currentPl.getName());
            lineInfo.setValue(Convert.toStr(currentPl.getId()));
            lineInfos.add(lineInfo);
        }
        return lineInfos;
    }
}
